Segmentação de clientes de um supermercado
1.Introdução
Este é o meu primeiro projeto end-to-end, por isso, é o mais simples do meu portifólio.
O objetivo deste projeto é segmentar os clientes de um supermercado com base em seus perfis de compra, utilizando o algoritmo K-Means e o método do cotovelo. Também será realizada uma análise descritiva dos dados.
Ao final, espera-se obter insights sobre os perfis de clientes e seus padrões de consumo, o que pode ser útil na criação de campanhas de marketing personalizadas.
Os dados utilizados são reais e pertencem a um supermercado dos Estados Unidos chamado Hunter’s. A base de dados está disponível no Kaggle e possui 12 colunas com mais de 2 milhões de registros de compras.
2. Tecnologias
Foi utilizado a linguagem R, o Excel e o Power BI
3. Carregar pacotes
library(gmodels)
library(dplyr)
library(data.table)
library(tidyr)
library(ggplot2)
library(tidyverse)
library(factoextra)
library(scales) #escala nos gráficos
library(corrplot)#Gráfico de correlação
library(vcd)
library(cluster)
# Tabela interativa
library(DT)
# Gráficos interativos
library(ggplot2)
library(plotly)
library(htmlwidgets) # Opção 1 - Salvar gráfico em HTML
library(htmltools) # Opção 2 - Salvar gráfico em HTML4. Carregar a base de dados
dados <- read.csv("C:/0.Projetos/1.Projeto-Supermercado/Dataset/Supermarket_dataset_for_predictive_marketing_2023.csv")4.1 Conhecer os dados
O conjunto de dados têm 2.019.501 linhas e 12 colunas.
Colunas da tabela:
order_id – Um número único para identificar o pedido
user_id – Um número único para identificar o usuário
order_number – Número do pedido
order_dow – Dia da semana em que o pedido foi feito
order_hour_of_day – Hora do pedido
days_since_prior_order – Histórico do pedido
product_id – ID do produto
add_to_cart_order – Número de itens adicionados ao carrinho
reordered – Se o novo pedido ocorreu
department_id – Número único atribuído a cada departamento
department – Nomes dos departamentos
product_name – (Nome dos produtos)
#Numero de linhas e colunas
n_linhas <- nrow(dados)
n_colunas <- ncol(dados)
cat("O conjunto de dados tem", n_linhas, "linhas e", n_colunas, "colunas.")## O conjunto de dados tem 2019501 linhas e 12 colunas.
## order_id user_id order_number
## "integer" "integer" "integer"
## order_dow order_hour_of_day days_since_prior_order
## "integer" "integer" "numeric"
## product_id add_to_cart_order reordered
## "integer" "integer" "integer"
## department_id department product_name
## "integer" "character" "character"
5.Limpeza dos dados
5.1 Verificação de dados nulos
A única coluna com NA´s é days_since_prior_order ( Histórico do pedido).
## order_id user_id order_number
## 0.000000 0.000000 0.000000
## order_dow order_hour_of_day days_since_prior_order
## 0.000000 0.000000 6.157066
## product_id add_to_cart_order reordered
## 0.000000 0.000000 0.000000
## department_id department product_name
## 0.000000 0.000000 0.000000
Observamos abaixo que o histórico de pedidos vai até 30 dias. Então, as NA´s serão retiradas, pois elas correspondem a clientes que não compraram no período de 30 dias ou clientes novos.
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 0.00 5.00 8.00 11.39 15.00 30.00 124342
5.2 Eliminação de NA´s
#Eliminamos as NA
#Cria-se uma nova base de dados elimando as NA´s
dados2 <- dados[!is.na(dados$days_since_prior_order), ]## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 5.00 8.00 11.39 15.00 30.00
## [1] "numeric"
Sobre a variável “days_since_prior_order” :
1. Observa-se que o número maximo de dias desde a última compra é 30, logo, pode-se supor que essa contagem é mensal.
2. O mínimo de dias é 0, isso pode indicar novos clientes. E, 25% dos dados têm uma variação de 5 dias entres as compras.
3. A mediana é 8, isso significa que metade dos clientes tem 8 dias de diferenças entre as compras.
4. As NA´s podem indicar clientes que não fazem compras a mais de 1 mês.
Após a limpeza dos dados, descobrimos que 105.273 clientes na tabela.
#Saber quantos user id tem na base de dados
#unique: vai considerar os unicos dados
user_id_unicos <- unique(dados$user_id)
#lenght:quantos tem na lista de unique
n_user_id_unicos <- length(user_id_unicos)
cat("O conjunto de dados tem", n_user_id_unicos, "clientes")## O conjunto de dados tem 105273 clientes
6. Transformação dos dados
6.1 Tabela com histórico de compras agrupado
Será feito agrupamento dos clientes para encontrar o histórico de compra de cada um.
6.2 Tabela com os departamentos transpostos com colunas
Os departamentos estão inseridos como linha, por isso, será feita suas transposição para que eles sejam considerados colunas e utilizados no clustering.
6.3 União das tabelas
Agora, as tabelas com os históricos de compra e transposição dos departamentos será unida. Dessa forma, obtemos a tabela final para a segmentação.
7. Análise Descritiva
7.1 Frequência de compra dos clientes
O objetivo é responder a seguinte pergunta: Quantas vezes por mês um cliente costuma ir ao mercado?
Observa-se que a maioria dos clientes realiza compras uma vez por mês (19,93%), seguida por aqueles que compram semanalmente (8,72%).
É possível que o comportamento de compra mensal esteja relacionado ao recebimento de salário, o que leva a compras maiores em um único momento. Essa informação pode ser útil para o supermercado planejar a reposição de mercadorias no início ou no final do mês.
Além disso, há um potencial para o aumento da frequência de compra. Estratégias como programas de fidelidade ou cupons semanais podem incentivar os clientes a retornarem com mais frequência.
7.1.1 Tabela com a frequência de compra
#Criar uma tabela de frequencia
freq_compra <- table(final_df$max_dias_desde_a_ultima_compra)
#freq_compra
# Converter a tabela de frequência em um dataframe
freq_compra1 <- as.data.frame(freq_compra)
#freq_compra1
#Nomear as colunas
names(freq_compra1) <- c("Quantidade_de_dias_entre_as_compras", "Frequencia")
#names(freq_compra1)
# Ordenar o dataframe em ordem decrescente
freq_compra_ordenada <- freq_compra1 %>%
arrange(desc(Frequencia)) %>%
mutate(
Porcentagem_da_freq = round((Frequencia / sum(Frequencia) * 100), 2)
)
# Exibir Resultado
datatable(
freq_compra_ordenada,
options = list(
dom = 't' #, # Só a tabela
#pageLength = 5 # Nº de linhas exibidas
),
rownames = FALSE, # Remover numeração das linhas
caption = "Frequência de compra dos clientes"
)7.1.2 Gráfico Interativo com a frequência de compra
# Alguns clientes compram a cada 7 dias e outros que compram a cada 30 dias
# Gráfico de Frequência das compras
grafico_freq <- ggplot(final_df, aes(x = max_dias_desde_a_ultima_compra)) +
geom_histogram(fill = "#275317", color = "white", bins = 30) +
labs(
title = "Frequência de Compras dos Clientes",
x = "Dias desde a última compra",
y = "Número de Clientes"
) +
theme_minimal(base_size = 14)
# Tornar o gráfico interativo
grafico_freq1 <- ggplotly(grafico_freq) %>%
config(displayModeBar = FALSE) %>% # Desativa a barra de ferramentas superior e o zoom com o scroll
layout(
xaxis = list(fixedrange = TRUE), # Desativa o zoom no eixo X
yaxis = list(fixedrange = TRUE) # Desativa o zoom no eixo Y
)
grafico_freq17.2 Qual dia os clientes costumam ir mais vezes ao supermercado?
Esta pergunta é importante, pois, ajudaria o supermercado a alocar mais funcionários nos dias de maior movimento. Além de melhorar o planejamento do estoque.
De acordo com os dados, Domingo e Segunda-feira são os dias com maior fluxo de clientes. Portanto, é estratégico reforçar a equipe nesses dias e fazer a reposição dos produtos nas prateleiras no sábado.
Como Quarta e Quinta apresentam menor movimento, seria interessante criar ofertas/promoções para atrair mais clientes.
7.2.1 Tabela com a quantidade de clientes por dia
# Tabela de frequência
tabela_frequencia <- table(dados$order_dow)
# Converter para data.frame
tabela_grafico <- as.data.frame(tabela_frequencia)
names(tabela_grafico) <- c("Dia_da_compra", "Frequencia")
# Substituir os números pelos nomes dos dias da semana
dias_semana <- c("Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado")
tabela_grafico$Dia_da_compra <- factor(
dias_semana[as.numeric(as.character(tabela_grafico$Dia_da_compra)) + 1],
levels = dias_semana )7.2.2 Gráfico Interativo com a quantidade de clientes por dia
grafico_dias <- ggplot(tabela_grafico, aes(x = Dia_da_compra, y = Frequencia)) +
geom_bar(stat = "identity", fill = "#275317") +
labs(
title = "Dia com mais visitas ao mercado",
x = "Dia da compra",
y = "Frequência (em milhares)"
) +
scale_y_continuous(labels = label_number(scale = 1e-3)) +
theme_minimal(base_size = 14)
# Tornar interativo
grafico_dias1 <- ggplotly(grafico_dias) %>%
config(displayModeBar = FALSE) %>% # Desativa a barra de ferramentas superior e o zoom com o scroll
layout(
xaxis = list(fixedrange = TRUE), # Desativa o zoom no eixo X
yaxis = list(fixedrange = TRUE) # Desativa o zoom no eixo Y
)
grafico_dias1 7.3 Departamentos que vendem mais itens
Apesar do dataset não ter o valor dos produtos, saber quais departamentos vendem mais pode ser um indicativo de onde vem a maior parte do lucro do supermercado.
Observa-se que os departametos que mais vende são respectivamente: produce, dairy eggs, snacks.
No final deste tópico, traduzi o nome dos departamentos com mais vendas.
Os departamentos de hortifruit, Ovos e laticínios são os que mais vendem. Esses produtos são utilizados no cotidiano das pessoas, o que indica que este estabelecimento é usado para compras regulares e não apenas emergenciais.
Além disso, esses produtos tem validade curta, logo é importante que o supermercado procure fornecedores próximos ou melhore a logística ao comprar de fornecedores distantes.
Snacks (Lanches, Petiscos e Biscoitos) é o terceiro departamento com mais vendas. Esses alimentos são muito atrativos para crianças, então seria estratégico colocá-los em prateleiras baixas para que as crianças consigam alcançar.
Os departamentos de Frios (ex: queijos) e Padaria também estão entre o top 10 de vendas. Assim, para aumentar o ticket médio, o supermercado poderia oferecer “combos matinais” (leite+queijo+ovos+pão) com preços promocionais nos dias de menor movimento.
7.3.1 Contagem de itens, por departamento, comprados por cada cliente
#Tabela que agrupa por departamento e conta os itens que cada cliente compra
df_grupo <- dados2 %>%
group_by(user_id, department) %>%
summarise(count = n())
# Exibir Resultado
datatable(
df_grupo,
options = list(
dom = 't' #, # Só a tabela
#pageLength = 5 # Nº de linhas exibidas
),
rownames = FALSE, # Remover numeração das linhas
caption = "Contagem de itens, por departamento, comprados por cada cliente"
)